package cn.skyquant.quant4j.service.boot.model.authority;

import cn.skyquant.quant4j.api.authority.AuthorityService;
import cn.skyquant.quant4j.api.authority.UserDTO;
import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.sdk.util.bean.BeanTools;
import cn.skyquant.quant4j.sdk.util.digest.Password;
import cn.skyquant.quant4j.sdk.util.string.StringUtils;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.Optional;
import java.util.Set;

@Service("AuthorityServiceImpl")

public class AuthorityServiceImpl implements AuthorityService {

    @Autowired
    UserRepository userRepository;

    static final ResultDTO error1 = ResultDTO.error("登录失败,手机号或密码不存在");
    static final ResultDTO error2 = ResultDTO.error("登录失败,手机号或密码不匹配");
    static final ResultDTO error3 = ResultDTO.error("用户不存在");
    static final ResultDTO error4 = ResultDTO.error("校验令牌缺失参数");
    static final ResultDTO error5 = ResultDTO.error("校验手机号和令牌失败");
    static final ResultDTO error6 = ResultDTO.error("校验令牌缺失参数");
    static final ResultDTO error7 = ResultDTO.error("参数不完整");
    static final ResultDTO error8 = ResultDTO.error("更新失败,手机号和原密码不匹配");
    static final ResultDTO error9 = ResultDTO.error("注册失败,该手机号已经被注册");
    static final ResultDTO error10 = ResultDTO.error("注册失败,系统错误");
    static final ResultDTO error11 = ResultDTO.error("未找到用户");

    @Override
    public ResultDTO<UserDTO> get(Integer id) {
        Optional<User> optionalUser =  userRepository.findById(id);
        if(optionalUser.isPresent()){
            UserDTO userDTO = convertUserToDTO(optionalUser.get());
            return ResultDTO.success(userDTO);
        }else {
            return error11;
        }
    }

    @Override
    public ResultDTO<UserDTO> findByTel(String tel) {
        Optional<User> user= userRepository.findByTel(tel);
        if(user.isPresent()){
            UserDTO userDTO = convertUserToDTO(user.get());
            return ResultDTO.success(userDTO);
        }else {
            return error11;
        }
    }

    @Transactional
    //用手机号和密码登录
    public ResultDTO<UserDTO> login(String tel, String password) {
        Optional<User> userOptional = userRepository.findByTel(tel);
        if (userOptional.isPresent()) {
            String md5password = Password.gen(tel, password);
            if (md5password == null) {
                return error1;
            }
            User user = userOptional.get();
            if (md5password.equals(user.password)) {
                //登录成功，生成token和gmt_last_login
                user.gmtLastLogin = new Date();//修改gmt_last_login
                user.token = StringUtils.genString(6);//修改token
                UserDTO userDTO = convertUserToDTO(user);
                return ResultDTO.success(userDTO);
            }else {
                return error2;
            }
        }
        return error3;
    }

    @Override
    public ResultDTO<UserDTO> reg(String tel, String name, String password) {
        Optional<User> user = userRepository.findByTel(tel);
        if(user.isPresent()){
            return error9;
        }
        String md5password = Password.gen(tel,password);
        User newUser = new User();
        newUser.tel =  tel;
        newUser.name = name;
        newUser.password = md5password;
        newUser.roles = Sets.newHashSet(Role.guest);
        User dbUser = userRepository.save(newUser);
        if(dbUser.id!=null){
            UserDTO userDTO = convertUserToDTO(dbUser);
            return ResultDTO.success(userDTO);

        }
        return error10;
    }

    //校验token
    @Transactional
    public ResultDTO<Void> logout(Integer id){
        Optional<User> optionalUser = userRepository.findById(id);
        if(optionalUser.isPresent()){
            User user = optionalUser.get();
            user.token = null;
            return ResultDTO.success();
        }else {
            return ResultDTO.error();
        }
    }

    //仅做校验
    public ResultDTO<UserDTO> verifyToken(String tel, String token) {
        if (tel == null || token == null) {
            return error4;
        }
        Optional<User> userOptional = userRepository.findByTel(tel);
        if (userOptional.isPresent()) {
            User user = userOptional.get();
            if (token.equals(user.token)) {
                UserDTO userDTO = convertUserToDTO(user);
                return ResultDTO.success(userDTO);
            }
        }
        return error5;
    }

    @Override
    public ResultDTO<UserDTO> verifyPassword(String tel, String password) {
        if (tel == null || password == null) {
            return error6;
        }
        Optional<User> userOptional = userRepository.findByTel(tel);
        if (userOptional.isPresent()) {
            User user = userOptional.get();
            if (password.equals(user.password )) {
                UserDTO userDTO = convertUserToDTO(user);
                return ResultDTO.success(userDTO);
            }
        }
        return error5;
    }

    //更新账户信息
    @Override
    @Transactional
    public ResultDTO<Void> update(String tel, String newName, String newPassword) {
        if(tel==null || newName==null || newPassword==null){
            return error7;
        }
        Optional<User> userOptional = userRepository.findByTel(tel);
        if (userOptional.isPresent()) {
            User user = userOptional.get();
            user.password =  Password.gen(tel, newPassword);
            user.name = newName;
            return ResultDTO.success();
        }
        return error3;
    }

    //转换
    private UserDTO convertUserToDTO(User user) {
        UserDTO userDTO = new UserDTO();
        BeanTools.copyPublicFields(user, userDTO);
        Set<Role> roles = user.roles;
        if (!CollectionUtils.isEmpty(roles)) {
            for (Role role : roles) {
                if(role.name!=null){
                    userDTO.addRole(role.name);
                }
            }
        }
        return userDTO;
    }

}
